package com.zh.netty.bio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;


/**
 * 测试BIO
 * Java BIO 产生的问题
 *
 * 1. 每个请求都需要创建独立的线程，与对应的客户端进行数据Read,业务处理，数据write
 * 2. 当并发数较大时，需要创建大量线程来处理连接，系统资源占用较大。
 * 3. 连接建立后，如果当前线程暂时没有数据可读，则线程就阻塞在Read操作上，造成线程资源浪费
 */
public class BIOServer {

    public static void main(String[] args) throws IOException {

        /**
         * 1. 使用线程池机制，根据阿里巴巴开发手册，
         * 使用new  ThreadPoolExecutor(int corePoolSize,
         *                               int maximumPoolSize,
         *                               long keepAliveTime,
         *                               TimeUnit unit,
         *                               BlockingQueue<Runnable> workQueue,
         *                               ThreadFactory threadFactory,
         *                               RejectedExecutionHandler handler) 的方式创建
         * 参数说明：
         *  corePoolSize： 核心线程池大小
         *  maximumPoolSize： 最大线程池数
         *  keepAliveTime：  线程最大空闲时间
         *  unit：  时间单位
         *  workQueue： 线程等待队列
         *  threadFactory： 线程创建工厂
         *  handler： 拒绝策略
         */

        ExecutorService poolExecutor = new ThreadPoolExecutor(10
                , 10
                , 10L
                , TimeUnit.MICROSECONDS
                , new ArrayBlockingQueue<>(2)
                , Executors.defaultThreadFactory()
                , new ThreadPoolExecutor.AbortPolicy());

        // 2. 如果又客户端连接，就创建一个线程，与之通信
        // 创建ServerSocker, 参数为监听的端口
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器启动了");

        while (true){
            // 监听， 等待客户端连接
            final Socket accept = serverSocket.accept();
            System.out.println("===连接到一个客户端===");

            // 就创建一个线程，与之通信

            poolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    // 可以和客户端通讯
                    handler(accept);
                }
            });
        }
    }

    // 编写一个handler 方法，和客户端通讯
    public static void handler(Socket socket){
        System.out.println("线程信息 id:"+Thread.currentThread().getId()+",名称："+Thread.currentThread().getName());
        try {
            byte[] bytes = new byte[1024];
            // 通过socker 获取输入流
            InputStream inputStream = socket.getInputStream();

            // 循环读取客户端发送的数据
            while (true){
                System.out.println("线程信息 id:"+Thread.currentThread().getId()+",名称："+Thread.currentThread().getName());
                int read = inputStream.read(bytes);
                if(read != -1){
                    System.out.println(new String(bytes,0,read)); // 输出客户端发送的数据
                }else{
                    break;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            System.out.println("关闭和client的连接");
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
